﻿using System;
using System.ComponentModel.DataAnnotations;
using System.ServiceModel.DomainServices.Client;
using System.ServiceModel.DomainServices.Client.ApplicationServices;
using Komunikator.Web.Resources;

namespace Komunikator.Web
{
    public class ChangePasswordInfo : Entity
    {
        /// <summary>
        /// Gets or sets a function that returns old password.
        /// </summary>
        internal Func<string> OldPasswordAccessor { get; set; }

        /// <summary>
        /// Gets and sets old password.
        /// </summary>
        [Required(ErrorMessageResourceName = "ValidationErrorRequiredField", ErrorMessageResourceType = typeof(ValidationErrorResources))]
        [Display(Order = 1, Name = "OldPasswordLabel", ResourceType = typeof(RegistrationDataResources))]
        public string OldPassword
        {
            get
            {
                return (this.OldPasswordAccessor == null) ? string.Empty : this.OldPasswordAccessor();
            }
            set
            {
                this.RaisePropertyChanged("OldPassword");
            }
        }

        /// <summary>
        /// Gets or sets a function that returns the password.
        /// </summary>
        internal Func<string> NewPasswordAccessor { get; set; }

        /// <summary>
        /// Gets and sets the password.
        /// </summary>
        [Required(ErrorMessageResourceName = "ValidationErrorRequiredField", ErrorMessageResourceType = typeof(ValidationErrorResources))]
        [Display(Order = 2, Name = "NewPasswordLabel", Description = "PasswordDescription", ResourceType = typeof(RegistrationDataResources))]
        [RegularExpression("^.*[^a-zA-Z0-9].*$", ErrorMessageResourceName = "ValidationErrorBadPasswordStrength", ErrorMessageResourceType = typeof(ValidationErrorResources))]
        [StringLength(50, MinimumLength = 7, ErrorMessageResourceName = "ValidationErrorBadPasswordLength", ErrorMessageResourceType = typeof(ValidationErrorResources))]
        public string NewPassword
        {
            get
            {
                return (this.NewPasswordAccessor == null) ? string.Empty : this.NewPasswordAccessor();
            }

            set
            {
                this.ValidateProperty("NewPassword", value);
                this.CheckPasswordConfirmation();

                // Do not store the password in a private field as it should
                // not be stored in memory in plain-text.  Instead, the supplied
                // PasswordAccessor serves as the backing store for the value.

                this.RaisePropertyChanged("NewPassword");
            }
        }

        /// <summary>
        /// Gets or sets a function that returns the password confirmation.
        /// </summary>
        internal Func<string> PasswordConfirmationAccessor { get; set; }

        /// <summary>
        /// Gets and sets the password confirmation string.
        /// </summary>
        [Required(ErrorMessageResourceName = "ValidationErrorRequiredField", ErrorMessageResourceType = typeof(ValidationErrorResources))]
        [Display(Order = 3, Name = "PasswordConfirmationLabel", ResourceType = typeof(RegistrationDataResources))]
        public string PasswordConfirmation
        {
            get
            {
                return (this.PasswordConfirmationAccessor == null) ? string.Empty : this.PasswordConfirmationAccessor();
            }

            set
            {
                this.ValidateProperty("PasswordConfirmation", value);
                this.CheckPasswordConfirmation();

                // Do not store the password in a private field as it should
                // not be stored in memory in plain-text.  Instead, the supplied
                // PasswordAccessor serves as the backing store for the value.

                this.RaisePropertyChanged("PasswordConfirmation");
            }
        }

        /// <summary>
        /// Checks to ensure the password and confirmation match.  If they don't match,
        /// then a validation error is added.
        /// </summary>
        private void CheckPasswordConfirmation()
        {
            // If either of the passwords has not yet been entered, then don't test for equality between
            // the fields.  The Required attribute will ensure a value has been entered for both fields.
            if (string.IsNullOrWhiteSpace(this.NewPassword)
                || string.IsNullOrWhiteSpace(this.PasswordConfirmation))
            {
                return;
            }

            // If the values are different, then add a validation error with both members specified
            if (this.NewPassword != this.PasswordConfirmation)
            {
                this.ValidationErrors.Add(new ValidationResult(ValidationErrorResources.ValidationErrorPasswordConfirmationMismatch, new string[] { "PasswordConfirmation", "Password" }));
            }
        }
    }
}